package com.sudo.boot.service.sys.jobservice.aspect;

import cn.hutool.core.exceptions.ExceptionUtil;
import com.sudo.boot.base.constant.SysConstant;
import com.sudo.boot.base.exception.BizException;
import com.sudo.boot.base.pojo.JsonRes;
import com.sudo.boot.base.util.HttpServletUtil;
import com.sudo.boot.base.util.ResponseUtil;
import com.sudo.boot.base.util.ThreadLocalUtil;
import com.sudo.boot.common.constant.enums.SysJobAction;
import com.sudo.boot.common.constant.enums.ThrowOrReturn;
import com.sudo.boot.common.util.task.TaskUtil;
import com.sudo.boot.service.sys.jobservice.LogAndEmailService;
import com.sudo.boot.service.sys.jobservice.runnable.NextJobUtil;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.MDC;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.lang.reflect.Method;
import java.util.Map;

@Slf4j
@Aspect
@Component
public class VerifyTaskRequestAspect {

    @Resource
    private LogAndEmailService logAndEmailService;

    // 配置织入点
    @Pointcut("@within(com.sudo.boot.grpc.annotation.TaskComponent)")
    public void pointCut() {
    }

    /**
     * 前置通知：用于拦截操作
     */
    @Before("pointCut()")
    public void doBefore(){
        Map<String, Object> tlMap = ThreadLocalUtil.getTlMap();
        typeLog(tlMap,"任务开始执行");
    }


    @AfterReturning(value = "pointCut()")
    public void doAfterReturning(){
        Map<String, Object> tlMap = ThreadLocalUtil.getTlMap();
        typeLog(tlMap,"任务执行成功");
        doAfter(tlMap,ThrowOrReturn.RETURN,null);
    }

    @AfterThrowing(value = "pointCut()",throwing = "throwable")
    public void doAfterThrowing(Throwable throwable){
        Map<String, Object> tlMap = ThreadLocalUtil.getTlMap();
        typeLog(tlMap,"任务执行失败");
        doAfter(tlMap,ThrowOrReturn.THROW,throwable);
    }

    private void typeLog(Map<String, Object> tlMap,String title) {
        log.info("{}：{}#{}, paramMap：{}",title, tlMap.get("tl_jobBean"),tlMap.get("tl_jobMethod"),tlMap.get("tl_jobParams"));
    }

    private void doAfter(Map<String, Object> tlMap,ThrowOrReturn throwOrReturn,Throwable throwable) {
        JsonRes<String> jsonRes = new JsonRes<>();
        jsonRes.setCode(200);
        jsonRes.setTraceId(MDC.get(SysConstant.TRACE_ID));
        if (throwable != null) {
            jsonRes.setCode(500);
            jsonRes.setMsg(ExceptionUtil.getMessage(throwable));
            // ExceptionUtil.stacktraceToString(throwable) 会限制字符
            // 可通过ExceptionUtil.stacktraceToString(throwable, 100000) 自定义长度
            jsonRes.setData(ExceptionUtil.stacktraceToString(throwable));
        }
        HttpServletResponse response = HttpServletUtil.getResponse();
        ThreadLocalUtil.removeTlMap();
        // 运行子任务
        int jobId = Integer.parseInt(tlMap.get("tl_jobId").toString());
        NextJobUtil.runNextLocalJobs(jobId, throwOrReturn);
        MDC.clear();
        if (response == null) {
            logAndEmailService.asyncLocalJobLogAndEmail(tlMap,jsonRes, SysJobAction.AUTO);
        }else {
            logAndEmailService.asyncLocalJobLogAndEmail(tlMap,jsonRes, SysJobAction.MANUAL);
            ResponseUtil.res(jsonRes);
        }
    }

}
